home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
SourceCode
/
MiscKit1.7.1
/
MiscKit
/
Temp
/
MiscPickList
/
MiscPickList.m
< prev
next >
Wrap
Text File
|
1995-04-12
|
8KB
|
333 lines
//
// MiscPickList.m -- Pick List
// Written by Don Yacktman Copyright (c) 1994 by Don Yacktman.
// Version 0.1. All rights reserved.
//
// This notice may not be removed from this source code.
//
// This object is included in the MiscKit by permission from the author
// and its use is governed by the MiscKit license, found in the file
// "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
// for a list of all applicable permissions and restrictions.
//
#import "MiscPickList.h"
#import <sys/param.h>
#define MISC_PickListExtension "picklist"
static MiscDictionary *availableLists = nil;
@interface MiscPickList(private)
- _enableButtons:(BOOL)flag;
- _updateBrowser;
@end
@implementation MiscPickList(private)
- _enableButtons:(BOOL)flag
{
[modifyButton setEnabled:flag];
[addButton setEnabled:flag];
return self;
}
- _updateBrowser
{
// adds/removes the items in the browser as necessary
int i, cnt;
[self loadNibIfNeeded];
cnt = [sortedKeys count];
[browser renewRows:cnt cols:1];
for (i=0; i<cnt; i++) {
id newCell = [browser cellAt:i :0];
[newCell setTag:i];
[newCell setTitle:[[sortedKeys objectAt:i] stringValue]];
}
[[browser sizeToCells] display];
return self;
}
@end
@implementation MiscPickList
+ findPickListNamed:(MiscString *)aName
{
if (!availableLists) {
availableLists = [[MiscDictionary alloc] init];
}
if ([availableLists isKey:aName]) {
return [availableLists valueForKey:aName];
} else {
MiscPickList *theList = [[self alloc] initForListNamed:aName];
[availableLists insertKey:aName value:theList];
return theList;
}
return nil;
}
+ (MiscString *)pickListExtension
{
static id theExtension = nil;
if (!theExtension)
theExtension = [MiscString newWithString:MISC_PickListExtension];
return theExtension;
}
+ (MiscString *)fileNameForPickListNamed:(MiscString *)aName
{
char path[MAXPATHLEN+1];
char *file; MiscString *fileName;
if ([[NXBundle mainBundle] getPath:path
forResource:[aName stringValue]
ofType:[[self pickListExtension] stringValue]])
return [MiscString newWithString:path];
// Couldn't find it in the app bundle, so we'll check the
// various libraries and see what we can find...
if (![MiscFileFinder findFileTypeNamed: "PickLists"]) {
[[MiscFileFinder alloc] initName:"PickLists"
defaultPath:
"~/Library/PickLists:/Library/PickLists:/LocalLibrary/PickLists"
pathVariable:"PICKLISTPATH" mode:R_OK];
}
fileName = [[MiscString alloc] initFromFormat:"%s.%s",
[aName stringValue], [[self pickListExtension] stringValue]];
file = [[MiscFileFinder findFileTypeNamed:"PickLists"]
fullPathForFile:[fileName stringValue]];
[fileName free];
if (file) return [MiscString newWithString:file];
return nil; // couldn't find it.
}
- init
{
// return [self error:"Don't call MiscPickList's -init method!"];
return [self initForListNamed:[MiscString newWithString:"Default"]];
}
- free
{
[itemList freeObjects];
[itemList free];
[sortedKeys freeObjects];
[sortedKeys free];
[listPath free];
[listName free];
return [super free];
}
- initForListNamed:(MiscString *)aName
{
[super init];
autoSave = YES;
sortedKeys = [[List alloc] init];
itemList = nil;
[self loadItemList:nil name:aName];
return self;
}
- loadItemList:(MiscString *)aPath name:(MiscString *)aName
{
if (listName) [listName free];
listName = [aName copy];
if (listPath) [listPath free];
listPath = [aPath copy];
if (!listPath) {
listPath = [[self class] fileNameForPickListNamed:aName];
}
[self reloadItemList];
return self;
}
- reloadItemList;
{
if (itemList) {
[itemList freeObjects];
[itemList free];
}
itemList = MiscParseTableFile(listPath);
[sortedKeys freeObjects];
[sortedKeys empty];
{
void *k, *v;
NXHashState hs = [itemList initState];
while ([itemList nextState:&hs key:&k value:&v]) {
[sortedKeys addObject:[(id)k copy]];
}
[sortedKeys miscStringSort];
}
changed = NO;
return self;
}
- saveList { return [self saveListToPath:listPath]; }
- saveListToPath:(MiscString *)aPath
{
// ***** If we can't save to a global list, then we should try to
// save to a list in the user's ~Library directory.
MiscWriteTableFile(aPath, itemList);
changed = NO;
return self;
}
- popUp:sender
{
[self _updateBrowser];
[browser selectCellAt:0 :0];
[browser scrollCellToVisible:0 :0];
[entryText takeStringValueFrom:[self selectedKey]];
[[self window] setTitle:[listName stringValue]];
[[self window] makeKeyAndOrderFront:self];
// ***** probably want to position the window near the text field...
return self;
}
- popUpForTextPal:aTextField
{
[self setTextPal:aTextField];
return [self popUp:nil];
}
- doEntry:sender
{
[entryText takeStringValueFrom:[self selectedKey]];
[textPal takeStringValueFrom:[itemList valueForKey:[self selectedKey]]];
return self;
}
- finishEntry:sender
{
[self doEntry:sender];
[[self window] orderOut:self];
return self;
}
- addItem:sender
{
id theString = [MiscString new];
if (![entryText respondsTo:@selector(stringValue)]) return nil;
[theString takeStringValueFrom:entryText];
[self addItemToList:theString value:theString];
[self _enableButtons:NO];
return self;
}
- modifyItem:sender
{
// Take the selected key, delete it, and then do an add.
[[self window] disableDisplay];
[[self window] disableFlushWindow];
[self removeItemFromList:[self selectedKey]];
[self addItem:sender];
[self _enableButtons:NO];
[[self window] reenableDisplay];
[[self window] reenableFlushWindow];
[[self window] display];
return self;
}
- addItemToList:(MiscString *)anItem
{
[self addItemToList:anItem value:anItem];
return self;
}
- addItemToList:(MiscString *)anItem value:(MiscString *)aValue
{
BOOL haveIt = ([itemList isKey:anItem] ? YES : NO);
// return if already have key _and_ it has identical value:
if (haveIt) {
id existingValue = [itemList valueForKey:anItem];
if ([existingValue isEqual:aValue]) return nil; // no changes...
}
[[self window] disableDisplay];
[[self window] disableFlushWindow];
// add the item to the list, update the browser
[itemList insertKey:anItem value:aValue];
if (!haveIt) {
[sortedKeys addObject:anItem];
[sortedKeys miscStringSort];
[self _updateBrowser]; // browser displays keys, we only update
// if we didn't have the key before.
[self selectKey:anItem];
}
changed = YES;
if (autoSave) [self saveList];
[[self window] reenableDisplay];
[[self window] reenableFlushWindow];
[[self window] display];
return self;
}
- removeItemFromList:(MiscString *)anItem
{
int i;
if (![itemList isKey:anItem]) return nil;
[itemList removeKey:anItem];
for (i=0; i<[sortedKeys count]; i++) {
if ([[sortedKeys objectAt:i] isEqual:anItem]) {
[sortedKeys removeObjectAt:i];
changed = YES;
[self _updateBrowser];
if (autoSave) [self saveList];
return self;
}
}
return nil;
}
- (MiscDictionary *)itemList { return itemList; }
- (BOOL)isDirty { return changed; }
- (MiscString *)listPath { return listPath; }
- (MiscString *)listName { return listName; }
- (BOOL)autoSave { return autoSave; }
- setAutoSave:(BOOL)flag { autoSave = flag; return self; }
- browser { return browser; }
- entryText { return entryText; }
- textPal { return textPal; }
- setBrowser:anObject { browser = anObject; return self; }
- setEntryText:anObject { entryText = anObject; return self; }
- setTextPal:anObject { textPal = anObject; return self; }
- nibDidLoad
{
[browser setDoubleAction:@selector(finishEntry:)];
return [super nibDidLoad];
}
- (BOOL)textWillChange:textObject
{
[self _enableButtons:YES];
return NO;
}
- (MiscString *)selectedKey
{
static id aString = nil;
if (!aString) aString = [MiscString new];
[aString setStringValue:[[browser selectedCell] title]];
return aString;
}
- selectKey:(MiscString *)aKey
{
int i;
for (i=0; i<[sortedKeys count]; i++) {
if ([aKey isEqual:[sortedKeys objectAt:i]]) {
[browser selectCellAt:i :0];
[browser scrollCellToVisible:i :0];
[self doEntry:browser]; // as if they clicked here...
return self;
}
}
return nil;
}
@end